/* NOTICE
    OpenJaWS - Open Java Weather Station
    
    Copyright (C) 2008 Grant Gardner <grant@lastweekend.com.au>
    
    OpenJaWS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
NOTICE */

package au.com.lastweekend.openjaws.plugins;

import java.util.Date;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import au.com.lastweekend.openjaws.api.Readings;
import au.com.lastweekend.openjaws.api.WeatherPlugin;
import au.com.lastweekend.openjaws.api.WeatherPluginException;
import au.com.lastweekend.openjaws.api.WeatherStation;
import au.com.lastweekend.openjaws.api.WeatherStationException;

/**
 * Synchronises the weather station with local PC time. If the data is not within an allowed drift both the weather station and the
 * readingTime will be updated.
 * 
 * Assumes that the {@link CurrentReadingsPlugin} has called {@link Readings#setReadingTime(Date)} somewhere up the chain
 * (recently). It would be unwise to put heavy processing between this plugin and that which sets the readingTime.
 * 
 * 
 * Does nothing if the marker station value is set by {@link HistoricalReadingsPlugin}
 * 
 * @author grant@lastweekend.com.au
 * @version $Id: codetemplates.xml,v 1.2 2005/01/22 06:53:11 ggardner Exp $
 */
public class SynchroniseStationTimePlugin extends DecoratedWeatherPlugin {

    private static final Logger LOG = LoggerFactory.getLogger(SynchroniseStationTimePlugin.class);
    private WeatherStation ws;
    private int maxDrift = 5;

    public SynchroniseStationTimePlugin(WeatherStation ws, WeatherPlugin decorated) {

        super(decorated);
        this.ws = ws;
    }

    @PostConstruct
    public void init() {

        if (isEnabled()) {
            LOG.info("Enabled, maxDrift=" + getMaxDrift() + "s");
        } else {
            LOG.info("Disabled");
        }
    }

    @Override
    protected void preProcess(Readings readings) throws WeatherPluginException {

        if (!HistoricalReadingsPlugin.isHistoricalReading(readings)) {
            adjustTime(readings);
        }

    }

    private void adjustTime(Readings readings) {

        Date wsTime = readings.getReadingTime();

        long wsTimeMillis = wsTime.getTime();

        long currentTimeMillis = System.currentTimeMillis();
        long drift = currentTimeMillis - wsTimeMillis;

        if (LOG.isDebugEnabled()) {
            LOG.debug(String.format("Time drift - %dms", drift));
        }

        if (Math.abs(drift) > (maxDrift * 1000)) {
            Date localTime = new Date(currentTimeMillis);
            readings.setReadingTime(localTime);
            LOG.warn(String.format("Station time (%tc) out of synch with local time (%tc)", wsTime, localTime));
            try {
                ws.setCurrentTime(localTime);
            } catch (WeatherStationException e) {
                LOG.error("Unable to synchronise station time", e);
            }
        }

    }

    /**
     * Maximum clock drift in seconds before we try to reset the station clock
     * 
     * @return the maxDrift
     */
    public int getMaxDrift() {

        return maxDrift;
    }

    /**
     * Set the maximum drift in seconds before we try to reset the station clock
     * 
     * @param maxDrift
     *            the maxDrift to set - default 5 seconds
     */
    public void setMaxDrift(int maxDrift) {

        this.maxDrift = maxDrift;
    }

}
